<?php

namespace html;

class validator extends \system\core\validator
{

	function __construct($validator_definition_file=null)
	{
		if( !isset($validator_definition_file) ) $this->setDefinition("res/html_definition.cfg");
		else $this->setDefinition($validator_definition_file);
		$this->load_definition();
	}

	/**
	 * Sanitize inproper written tags and rewrite their blocktype based on definition
	 * @param array $objectArray
	 */
	public function sanitize_tag_types($doc)
	{
		$objectArray = $doc->getTags();
		if( $objectArray ) foreach( $objectArray as $key => $tag )
			{
				if( $this->struct->has("html->tag->".$tag->getTagname()."->issingle") )
				{
					$tag->setType("SINGLE");
				}
				if( $this->struct->has("html->tag->".$tag->getTagname()."->display") )
				{
					$tag->setBlocklevel($this->struct->get("html->tag->".$tag->getTagname()."->display"));
				}
				if( $this->struct->has("html->tag->".$tag->getTagname()."->dependancy") )
				{
					$tag->setDependancy($this->struct->get("html->tag->".$tag->getTagname()."->dependancy"));
				}
			}
	}

	//TODO Here is some work todo? tag->setText?
	public function sanitize_attributes($doc)
	{
		$objectArray = $doc->getTags();
		$htmlcode = $doc->getHtmlSource();

		if( $objectArray ) foreach( $objectArray as $key => $tag )
			{
				if( isset($objectArray[($key + 1)]) )
				{
					//echo $tag->endPos()."\n";
					//echo ($objectArray[($key + 1)]->startPos() - $tag->endPos())."\n";
					//echo $htmlcode."\n";
					//echo substr($htmlcode, $tag->endPos(), ($objectArray[($key + 1)]->startPos() - $tag->endPos()))."\n";
					$tag->setText(substr($htmlcode, $tag->endPos(), ($objectArray[($key + 1)]->startPos() - $tag->endPos())));
				}
				$tag->sanitizeAttributes($this->struct->get("html->tag->".$tag->getTagname()."->attributes"));
			}
	}

	private function create_structuremap($doc)
	{
		$objectArray = $doc->getTags();
		if( $objectArray ) foreach( $objectArray as $key => $tag )
			{
				$type = $tag->getType();
				$tagname = $tag->getTagname();
				$level = $tag->getLevel();

				if( $type == "OPEN" || $type == "CLOSE" )
				{
					$structureMap[$level][$tagname][$type][$key] = true;
					$structurePairs[$tagname][$type][$key] = true;
					$structureInfo[$level][$tagname]["typecount"][$type][$key] = true;
					$structureInfo[$level][$tagname]["typeamount"][$tagname][$key] = true;
					$structureInfo[$level][$tagname]["tagref"][] = $tag;
				}
			}
		return array(
					$structureMap,
					$structurePairs,
					$structureInfo
					);
	}

	public function check_integrity($doc)
	{
		list($structureMap,$structurePairs,$structureInfo) = $this->create_structuremap($doc);


//		print_r($structureMap);
/*
		if( $structureInfo )
		{
			krsort($structureInfo);
			foreach( $structureInfo as $level => $info )
			{

			}
		}
*/
		
		if( $structurePairs ) foreach( $structurePairs as $tagname => $typeArray )
			{
				$typecount["OPEN"] = count($typeArray["OPEN"]);
				$typecount["CLOSE"] = count($typeArray["CLOSE"]);

				if( $typecount["OPEN"] != $typecount["CLOSE"] )
				{
					$missing = max($typecount["OPEN"], $typecount["CLOSE"]) - min($typecount["OPEN"], $typecount["CLOSE"]);
					if( $typecount["OPEN"] > $typecount["CLOSE"] )
					{
						$tagtypemissing = "closing";
					}
					elseif( $typecount["OPEN"] < $typecount["CLOSE"] )
					{
						$tagtypemissing = "opening";
					}
					echo "There ".($missing > 1 ? "are" : "is")." {$missing} missing {$tagtypemissing} {$tagname} tags\n";
				}
			}

		if( $structureMap )
		{
			krsort($structureMap);

//			print_r($structureMap);
			foreach( $structureMap as $level => $tags )
			{
				foreach( $tags as $tagname => $typeArray )
				{

					$typecount["OPEN"] = count($typeArray["OPEN"]);
					$typecount["CLOSE"] = count($typeArray["CLOSE"]);

					if( $typecount["OPEN"] != $typecount["CLOSE"] )
					{
						if( is_array($typeArray["OPEN"]) )
						{
							$tagId = key($typeArray["OPEN"]);
							$tagTyp = "OPEN";
						}
						elseif( is_array($typeArray["CLOSE"]) )
						{
							$tagId = key($typeArray["CLOSE"]);
							$tagTyp = "CLOSE";
						}

						if( !$displace )
						{
							$displace = true;
							$correct = ($tagTyp == "OPEN" ? "CLOSE" : "OPEN");
							echo "Structure mismatch for {$tagTyp} tag {$tagname} id {$tagId} in level: {$level}\n";
							$this->reLevelStructure($doc, $tagId);
						}
						else
						{
							echo "Suck";
							$bagofSuck[] = $tagId;
						}

						//$this->reLevelTags()
					}
				}
			}

			/*
			print_r($bagofSuck);
			exit;
//			if( $objectArray ) foreach( $objectArray as $key => $tag )
			if( $bagofSuck )
			{
				foreach( $bagofSuck as $tagId )
				{
					if( $objectArray[$tagId]->getType() == $correct )
					{
						$objectArray[$tagId]->reLevel(-1);
					}
					//print_r($bagofSuck);
				}
				$this->check_integrity($doc);
			}

			 */
		}
	}

	public function reLevelStructure($doc, $offset)
	{
		if( $doc->getTags() ) foreach( $doc->getTags() as $tagId => $tag )
			{
				if($tagId == $offset) $tag->setType("SINGLE");
				elseif($tagId > $offset) $tag->reLevel(-1);
			}
		$this->check_integrity($doc);
	}

	public function x_check_integrity($doc)
	{
		$objectArray = $doc->getTags();
		if( $objectArray ) foreach( $objectArray as $key => $tag )
			{
				$type = $tag->getType();
				$tagname = $tag->getTagname();
				$level = $tag->getLevel();
				if( $type == "OPEN" || $type == "CLOSE" )
				{
					$structureMap[$level][$tagname][$type]++;
					$structurePairs[$tagname][$type]++;
					$structureInfo[$level][$tagname]["typecount"][$type]++;
					$structureInfo[$level][$tagname]["typeamount"][$tagname]++;
					$structureInfo[$level][$tagname]["tagref"][] = $tag;
				}
			}

		if( $structureInfo )
		{
			krsort($structureInfo);
			foreach( $structureInfo as $level => $info )
			{

			}
		}

		if( $structurePairs ) foreach( $structurePairs as $tagname => $typecount )
			{
				if( $typecount["OPEN"] != $typecount["CLOSE"] )
				{
					$missing = max($typecount["OPEN"], $typecount["CLOSE"]) - min($typecount["OPEN"], $typecount["CLOSE"]);
					if( $typecount["OPEN"] > $typecount["CLOSE"] )
					{
						$tagtypemissing = "closing";
					}
					elseif( $typecount["OPEN"] < $typecount["CLOSE"] )
					{
						$tagtypemissing = "opening";
					}
					echo "There ".($missing > 1 ? "are" : "is")." {$missing} missing {$tagtypemissing} {$tagname} tags\n";
				}
			}

		if( $structureMap )
		{
			krsort($structureMap);

			print_r($structureMap);

			foreach( $structureMap as $level => $tags )
			{
				foreach( $tags as $tagname => $typecount )
				{
					if( $typecount["OPEN"] != $typecount["CLOSE"] )
					{
						echo "Structure mismatch for tag {$tagname} in level: {$level}\n";
					}
				}
			}
		}
	}

}

?>
